#pragma once

#include <string>
#include <time.h>
#include <atomic>
#include <sys/stat.h>
#include <fstream>
#include <fcntl.h>
#include <unistd.h>
#include <vector>
#include <utility>

namespace ns_util
{
    // 路径模块
    class PathUtil
    {
#define DIR_PATH "./temp/"
    public:
        static std::string ContactFileSuffix(const std::string &filename, const std::string &suffix)
        {
            return DIR_PATH + filename + "." + suffix;
        }

        // 源文件
        static std::string SrcFile(const std::string &filename)
        {
            return ContactFileSuffix(filename, "cc");
        }

        // 可执行文件
        static std::string ExeFile(const std::string &filename)
        {
            return ContactFileSuffix(filename, "exe");
        }

        // 编译错误信息
        static std::string ErrFile(const std::string &filename)
        {
            return ContactFileSuffix(filename, "err");
        }

        // 标准输出
        static std::string StdoutFile(const std::string &filename)
        {
            return ContactFileSuffix(filename, "stdout");
        }

        // 标准输入
        static std::string StdinFile(const std::string &filename)
        {
            return ContactFileSuffix(filename, "stdin");
        }
        
        // 标准错误
        static std::string StderrFile(const std::string &filename)
        {
            return ContactFileSuffix(filename, "stderr");
        }
    };

    class FileUtil
    {
    public:
        static std::string UniqueFilename()
        {
            static std::atomic<int> count(0);
            return "temp_" + std::to_string(count++) + "_" + std::to_string(time(nullptr));
        }

        static bool WriteFile(const std::string &filename, const std::string &content)
        {
            std::string path = PathUtil::ContactFileSuffix(filename, "cc");
            int fd = open(path.c_str(), O_CREAT | O_WRONLY, 0644);
            if (fd < 0)
            {
                return false;
            }
            write(fd, content.c_str(), content.size());
            close(fd);
            return true;
        }

        static bool ReadFile(const std::string &path, std::string &content, bool keep = false)
        {
            content.clear();

            std::ifstream in(path);
            if (!in.is_open())
            {
                return false;
            }
            std::string line;
            // getline:不保存行分割符,有些时候需要保留\n,
            // getline内部重载了强制类型转化
            while (std::getline(in, line))
            {
                content += line;
                content += (keep ? "\n" : "");
            }
            in.close();
            return true;
        }

        static bool IsFileExist(const std::string &path)
        {
            struct stat st;
            return stat(path.c_str(), &st) == 0;
        }
    };

    class StringUtil
    {
    public:
        static void SplitString(const std::string &str, std::vector<std::string> &vec, const std::string &delimiter)
        {
            vec.clear();
            size_t start = 0;
            size_t pos = str.find(delimiter);
            while (pos != std::string::npos)
            {
                vec.push_back(str.substr(start, pos - start));
                start = pos + delimiter.size();
                pos = str.find(delimiter, start);
            }
            vec.push_back(str.substr(start));
        }

        static std::pair<bool, std::string> getHTTPHeaderValue(const std::string& header, const std::string& key, const std::string &fin, bool keep_key = false)
        {
            size_t pos = header.find(key);
            if (pos == std::string::npos) return std::make_pair(false, "");
            size_t len = key.size();
            size_t pos2 = header.find(fin, pos + len);
            std::string value = header.substr(pos + len, pos2 - pos - len);
            if (keep_key)
                value = key + value;
            return std::make_pair(true, value);
        }
    };
}